﻿using System;
using System.Diagnostics;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;


namespace StorageApp
{
    public static class KeyboardService
    {
        /// <summary>KeyboardType类型</summary>
        public enum KeyboardType
        {
            None = 0,
            /// <summary>字母数字键盘</summary>
            Alphabet,
            /// <summary>数字键盘</summary>
            Numeric,
        }
        public enum PlacementType
        {
            /// <summary>下左</summary>
            BottomStart,

            /// <summary>下中</summary>
            Bottom,

            /// <summary>下右</summary>
            BottomEnd,

            /// <summary>上左</summary>
            TopStart,

            /// <summary>上</summary>
            Top,

            /// <summary>上右</summary>
            TopEnd,
        }
        #region 依赖属性
        public static KeyboardType GetKbType(DependencyObject kbTypeProperty) => (KeyboardType)kbTypeProperty.GetValue(KbTypeProperty);
        public static void SetKbType(DependencyObject kbTypeProperty, KeyboardType value) => kbTypeProperty.SetValue(KbTypeProperty, value);

        public static readonly DependencyProperty KbTypeProperty = DependencyProperty.RegisterAttached(
            "KbType",
            typeof(KeyboardType),
            typeof(KeyboardService),
            new PropertyMetadata(
                defaultValue: KeyboardType.None,
                propertyChangedCallback: null,
                coerceValueCallback: OnKbTypeCallback
            )
        );

        public static PlacementType GetKbPlacement(DependencyObject kbPlacementProperty) => (PlacementType)kbPlacementProperty.GetValue(KbPlacementProperty);
        public static void SetKbPlacement(DependencyObject kbPlacementProperty, PlacementType value) => kbPlacementProperty.SetValue(KbPlacementProperty, value);

        public static readonly DependencyProperty KbPlacementProperty = DependencyProperty.RegisterAttached(
            "KbPlacement",
            typeof(PlacementType),
            typeof(KeyboardService),
            new PropertyMetadata(
                defaultValue: PlacementType.BottomStart,
                propertyChangedCallback: null,
                coerceValueCallback: (DependencyObject d, object baseValue) => {
                    return baseValue;
                }
            )
        );
        #endregion

        private static FrameworkElement? CurrentKeyboardElement;

        /// <summary>
        /// 事件绑定
        /// </summary>
        /// <param name="d"></param>
        /// <param name="baseValue"></param>
        /// <returns></returns>
        public static object? OnKbTypeCallback(DependencyObject d, object baseValue)
        {
            var element = (FrameworkElement)d;

            if (baseValue != null && (
                d.GetType() == typeof(System.Windows.Controls.TextBox) ||  
                d.GetType() == typeof(PasswordBox) ||
                d.GetType() == typeof(NumericUpDown) ||
                d.GetType() == typeof(System.Windows.Controls.ComboBox)
             )) {
                string popupName = "";

                switch (baseValue) {
                    case KeyboardType.Numeric:
                        popupName = "NumericKeyboardDom";
                        break;
                    case KeyboardType.Alphabet:
                        popupName = "AlphabetKeyboardDom";
                        break;
                }

                if (!string.IsNullOrEmpty(popupName)) {
                    // 点击处理
                    element.PreviewMouseUp += (object sender, MouseButtonEventArgs e) => {
                        TextBoxMouseLeftButtonDown(popupName, sender, e);
                    };

                    // 失去Focus处理
                    element.LostFocus += (object sender, RoutedEventArgs e) => {
                        TextBoxLostFocus(popupName, sender, e);
                    };
                }
            }

            return baseValue;
        }
        public static T? GetChildObject<T>(DependencyObject obj, string name) where T : FrameworkElement
        {
            if (obj == null)
            {
                return null;
            }

            for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);

                if (child is T t && (t.Name == name | string.IsNullOrEmpty(name)))
                {
                    return t;
                }
                else
                {
                    T grandChild = GetChildObject<T>(child, name);
                    if (grandChild != null)
                    {
                        return grandChild;
                    }
                }
            }
            return null;
        }

        /// <summary>文本输入框的点击处理</summary>
        private static void TextBoxMouseLeftButtonDown(string popupName, object sender, RoutedEventArgs e)
        {
            // 判断键盘是否开启
        
           
            CurrentKeyboardElement = (FrameworkElement)e.Source;

            var window = Window.GetWindow(CurrentKeyboardElement);
            if (window == null) return;

            Popup keyboardDom = GetChildObject<Popup>(window, popupName);
            if (keyboardDom == null) return;
            if(popupName== "AlphabetKeyboardDom")
            { 
                keyboardDom.Width = 600;
                keyboardDom.Height = 186;
            }
            else
            {
                keyboardDom.Width = 200;
                keyboardDom.Height = 186;
            }
            // 文本全选
            if (sender.GetType() == typeof(System.Windows.Controls.TextBox))
            {
                var textBox = (System.Windows.Controls.TextBox)sender;

                if (textBox.Text == "0")
                {
                    textBox.SelectAll();
                }
            }

            if (keyboardDom.PlacementTarget == null) {
                // 让Popup随着窗体的移动而移动
                window.LocationChanged += delegate {
                    if (keyboardDom.IsOpen == false) return;
                    MethodInfo mi = typeof(Popup).GetMethod("UpdatePosition", BindingFlags.NonPublic | BindingFlags.Instance);
                    mi.Invoke(keyboardDom, null);
                };
                // 让Popup随着窗体的Size改变而移动位置
                window.SizeChanged += delegate {
                    if (keyboardDom.IsOpen == false) return;
                    MethodInfo mi = typeof(Popup).GetMethod("UpdatePosition", BindingFlags.NonPublic | BindingFlags.Instance);
                    mi.Invoke(keyboardDom, null);
                };
                // 让Popup随着窗体的未激活而隐藏
                window.Deactivated += delegate {
                    keyboardDom.IsOpen = false;
                };
                // 让Popup随着窗体的点击而隐藏
                window.MouseLeftButtonDown += delegate {
                    keyboardDom.IsOpen = false;
                };
                // 让Popup打开处理位置
                keyboardDom.Opened += (object? sender, EventArgs e) => {
                    PlacementType placement = GetKbPlacement(CurrentKeyboardElement);
                    double keyboardWidth = keyboardDom.Width - 8;
                    double keyboardHeight = keyboardDom.Height - 6;
                    double elementWidth = CurrentKeyboardElement.ActualWidth;
                    double elementHeight = CurrentKeyboardElement.ActualHeight;
                    
                    switch (placement) {
                        case PlacementType.Bottom:
                            keyboardDom.VerticalOffset = 2;
                            keyboardDom.HorizontalOffset = (elementWidth - keyboardWidth) / 2;
                            break;
                        case PlacementType.BottomEnd:
                            keyboardDom.VerticalOffset = 2;
                            keyboardDom.HorizontalOffset = elementWidth - keyboardWidth;
                            break;
                        case PlacementType.TopStart:
                            keyboardDom.VerticalOffset = - (elementHeight + keyboardHeight);
                            keyboardDom.HorizontalOffset = 0;
                            break;
                        case PlacementType.Top:
                            keyboardDom.VerticalOffset = -(elementHeight + keyboardHeight);
                            keyboardDom.HorizontalOffset = (elementWidth - keyboardWidth) / 2;
                            break;
                        case PlacementType.TopEnd:
                            keyboardDom.VerticalOffset = -(elementHeight + keyboardHeight);
                            keyboardDom.HorizontalOffset = elementWidth - keyboardWidth;
                            break;
                        default:
                            keyboardDom.VerticalOffset = 2;
                            keyboardDom.HorizontalOffset = 0;
                            break;
                    }
                };
            }

            keyboardDom.PlacementTarget = CurrentKeyboardElement;
            var _id= VisualTreeHelper.GetChildrenCount(keyboardDom);
            NumberKeyboard keyboard = GetChildObject<NumberKeyboard>(window, "NumberKeyboard");

           
            keyboardDom.IsOpen = true;
        }
    
        /// <summary>键盘关闭处理</summary>
        public static void CloseKeyBoard(FrameworkElement mainContainer)
        {
            Popup alphabetKeyboardDom = GetChildObject<Popup>(mainContainer, "AlphabetKeyboardDom");
            Popup numericKeyboardDom =GetChildObject<Popup>(mainContainer, "NumericKeyboardDom");

            if (alphabetKeyboardDom != null) {
                alphabetKeyboardDom.IsOpen = false;
            }

            if (numericKeyboardDom != null) {
                numericKeyboardDom.IsOpen = false;
            }
        }
        public static T? GetParentObject<T>(DependencyObject obj, string name) where T : FrameworkElement
        {
            DependencyObject parent = VisualTreeHelper.GetParent(obj);

            while (parent != null)
            {
                if (parent is T t && (t.Name == name | string.IsNullOrEmpty(name)))
                {
                    return t;
                }
                parent = VisualTreeHelper.GetParent(parent);
            }

            return null;
        }

        /// <summary>文本输入框的失去Focus处理</summary>
        private static void TextBoxLostFocus(string popupName, object sender, RoutedEventArgs e)
        {
            var element = (FrameworkElement)sender;

            Grid mainContainer = GetParentObject<Grid>(element, "MainContainer");
            if (mainContainer == null) return;

            Popup keyboardDom = GetChildObject<Popup>(mainContainer, popupName);
            if (keyboardDom == null) return;

            if (element.Name == CurrentKeyboardElement?.Name) {
                keyboardDom.IsOpen = false;
            }
        }

        //public static void BindTo<T>() where T : UIElement
        //{
        //    EventManager.RegisterClassHandler(
        //        classType: typeof(T),
        //        routedEvent: UIElement.GotMouseCaptureEvent,
        //        handler: new RoutedEventHandler(TextBoxMouseLeftButtonDown),
        //        handledEventsToo: true);

        //    EventManager.RegisterClassHandler(
        //        classType: typeof(T),
        //        routedEvent: UIElement.LostFocusEvent,
        //        handler: new RoutedEventHandler(TextBoxLostFocus),
        //        handledEventsToo: true);
        //}
    }
}
